home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Disc to the Future 2
/
Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin
/
MAC
/
MPW_TOOL
/
TOOLS
/
TOOLS_WI
/
ICON_8
/
ICONT_FO
/
LMEM.C
< prev
next >
Wrap
Text File
|
1990-03-02
|
13KB
|
569 lines
/*
* lmem.c -- memory initialization and allocation; also parses arguments.
*/
#include "::h:config.h"
#include "tproto.h"
#include "globals.h"
#include "link.h"
#include "general.h"
/*
* The following code is operating-system dependent [@lmem.01]. It includes
* files that are system dependent.
*/
#if PORT
/* nothing is needed */
Deliberate Syntax Error
#endif /* PORT */
#if AMIGA || ATARI_ST || HIGHC_386 || MACINTOSH || VMS
/* nothing is needed */
#endif /* AMIGA || ATARI_AT || HIGHC_386 ... */
#if MSDOS
#if MICROSOFT
#include <sys/types.h>
#include <sys/stat.h>
#endif /* MICROSOFT */
#if TURBO
#include <sys/stat.h>
#endif /* TURBO */
#endif /* MSDOS */
#if MVS || VM
#include <file.h>
#endif /* MVS || VM */
#if OS2
#if MICROSOFT
#include <sys/types.h>
#include <sys/stat.h>
#endif /* MICROSOFT */
#endif /* OS2 */
#if UNIX
#ifndef ATT3B
#include <sys/types.h>
#include <sys/stat.h>
#endif /* ATT3B */
#endif /* UNIX */
/*
* End of operating-system specific code.
*/
/*
* Prototypes.
*/
hidden struct lfile *alclfile Params((char *name));
hidden int canread Params((char *file));
hidden novalue freelfile Params((struct lfile *p));
hidden int trypath Params((char *name,char *file));
/*
* Memory initialization
*/
struct gentry **lghash; /* hash area for global table */
struct ientry **lihash; /* hash area for identifier table */
struct fentry **lfhash; /* hash area for field table */
struct lentry *lltable; /* local table */
struct gentry *lgtable; /* global table */
struct centry *lctable; /* constant table */
struct ientry *litable; /* identifier table */
struct fentry *lftable; /* field table headers */
struct rentry *lrtable; /* field table record lists */
struct ipc_fname *fnmtbl; /* table associating ipc with file name */
struct ipc_line *lntable; /* table associating ipc with line number */
char *lsspace; /* string space */
word *labels; /* label table */
char *codeb; /* generated code space */
struct gentry *lgfree; /* free pointer for global table */
struct ientry *lifree; /* free pointer for identifier table */
struct fentry *lffree; /* free pointer for field table headers */
struct rentry *lrfree; /* free pointer for field table record lists */
struct ipc_fname *fnmfree; /* free pointer for ipc/file name table */
struct ipc_line *lnfree; /* free pointer for ipc/line number table */
char *lsfree; /* free pointer for string space */
char *codep; /* free pointer for code space */
char *lsend; /* pointer to end of string space */
static char *ipath; /* path for iconx */
#ifdef MultipleRuns
extern word pc;
extern int fatals;
extern int nlflag;
extern int lstatics;
extern int nfields;
#endif /* MultipleRuns */
/*
* linit - scan the command line arguments and initialize data structures.
*/
novalue linit()
{
struct gentry **gp;
struct ientry **ip;
struct fentry **fp;
llfiles = NULL; /* Zero queue of files to link. */
#ifdef EnvVars
ipath = getenv("IPATH");
#else /* EnvVars */
ipath = NULL;
#endif /* EnvVars */
if (ipath == NULL)
/*
* The following code is operating-system dependent [@lmem.02]. Set default for
* IPATH.
*/
#if PORT
/* something is needed */
Deliberate Syntax Error
#endif /* PORT */
#if AMIGA
/*
* There is no environment, so set ipath to the null string. The
* current directory is searched anyway and there is no symbol
* to force current path search.
*/
ipath = "";
#endif /* AMIGA */
#if ATARI_ST || UNIX
ipath = ".";
#endif /* ATARI_ST || UNIX */
#if HIGHC_386 || MSDOS || OS2
ipath = ";";
#endif /* HIGHC_386 || MSDOS || OS2 */
#if MACINTOSH
#if MPW || LSC
ipath = ":";
#endif /* MPW || LSC */
#endif /* MACINTOSH */
#if MVS || VM
ipath = "";
#endif /* MVS || VS */
#if VMS
ipath = "[]";
#endif /* VMS */
/*
* End of operating-system specific code.
*/
/*
* Allocate the various data structures that are used by the linker.
*/
lghash = (struct gentry **) tcalloc(ghsize, sizeof(struct gentry *));
lihash = (struct ientry **) tcalloc(ihsize, sizeof(struct ientry *));
lfhash = (struct fentry **) tcalloc(fhsize, sizeof(struct fentry *));
lltable = (struct lentry *) tcalloc(lsize, sizeof(struct lentry));
lctable = (struct centry *) tcalloc(csize, sizeof(struct centry));
lffree = lftable = (struct fentry *) tcalloc(fsize, sizeof(struct fentry));
lgfree = lgtable = (struct gentry *) tcalloc(gsize, sizeof(struct gentry));
lifree = litable = (struct ientry *) tcalloc(isize, sizeof(struct ientry ));
lnfree = lntable = (struct ipc_line*)tcalloc(nsize,sizeof(struct ipc_line));
lrfree = lrtable = (struct rentry *) tcalloc(rsize, sizeof(struct rentry));
lsfree = lsspace = (char *) tcalloc(stsize, sizeof(char));
lsend = lsspace + stsize - 1;
fnmtbl = (struct ipc_fname *) tcalloc(fnmsize, sizeof(struct ipc_fname));
fnmfree = fnmtbl;
labels = (word *) tcalloc(maxlabels, sizeof(word));
codep = codeb = (char *) tcalloc(maxcode, 1);
/*
* Zero out the hash tables.
*/
for (gp = lghash; gp < &lghash[ghsize]; gp++)
*gp = NULL;
for (ip = lihash; ip < &lihash[ihsize]; ip++)
*ip = NULL;
for (fp = lfhash; fp < &lfhash[fhsize]; fp++)
*fp = NULL;
#ifdef MultipleRuns
/*
* Initializations required for repeated program runs.
*/
pc = 0; /* In lcode.c */
nrecords = 0; /* In lglob.c */
#ifdef EvalTrace
colmno = 0; /* In link.c */
#endif /* EvalTrace */
lineno = 0; /* In link.c */
fatals = 0; /* In link.c */
nlflag = 0; /* In llex.c */
lstatics = 0; /* In lsym.c */
nfields = 0; /* In lsym.c */
#endif /* MultipleRuns */
/*
* Install "main" as a global variable in order to insure that it
* is the first global variable. iconx/start.s depends on main
* being global number 0.
*/
putglobal(instid("main"), F_Global, 0, 0);
}
#ifdef DeBugLinker
/*
* dumplfiles - print the list of files to link. Used for debugging only.
*/
novalue dumplfiles()
{
struct lfile *p,*lfls;
fprintf(stderr,"lfiles:\n");
lfls = llfiles;
while (p = getlfile(&lfls))
fprintf("stderr,'%s'\n",p->lf_name);
fflush(stderr);
}
#endif /* DeBugLinker */
/*
* alsolink - create an lfile structure for the named file and add it to the
* end of the list of files (llfiles) to generate link instructions for.
*/
static char *pptr;
novalue alsolink(name)
char *name;
{
struct lfile *nlf, *p;
char file[256], ok;
ok = 0;
if (canread(name)) {
ok++;
strcpy(file, name);
}
else {
/*
* Can't find name in current directory so try paths in
* ipath if there are any. (ipath cannot override the
* current directory first strategy so there is probably
* no reason to initialize ipath to the various current
* directory markers as is done above, since this will
* only result in a duplicate failed search. Note that
* the access test which is done above in some systems
* will have already caused ilink to exit if name is
* not found in the current directory anyway so ipath
* was never able to search other paths first in any case.)
*/
pptr = ipath;
while (trypath(name, file)) {
if (canread(file)) {
ok++;
break;
}
}
}
if (!ok)
quitf("cannot resolve reference to file '%s'",name);
nlf = alclfile(file);
if (llfiles == NULL) {
llfiles = nlf;
}
else {
p = llfiles;
while (p->lf_link != NULL) {
if (strcmp(p->lf_name,file) == 0)
return;
p = p->lf_link;
}
if (strcmp(p->lf_name,file) == 0)
return;
p->lf_link = nlf;
}
}
/*
* getlfile - return a pointer (p) to the lfile structure pointed at by lptr
* and move lptr to the lfile structure that p points at. That is, getlfile
* returns a pointer to the current (wrt. lptr) lfile and advances lptr.
*/
struct lfile *getlfile(lptr)
struct lfile **lptr;
{
struct lfile *p;
if (*lptr == NULL)
return (struct lfile *)NULL;
else {
p = *lptr;
*lptr = p->lf_link;
return p;
}
}
/*
* canread - see if file can be read and be sure that it's just an
* ordinary file.
*/
static int canread(file)
char *file;
{
/*
* The following code is operating-system dependent [@lmem.03]. Check to see if
* .u1 file can be read.
*/
#if PORT
/* something is needed */
Deliberate Syntax Error
#endif /* PORT */
#if AMIGA
char lclname[MaxFileName];
if (access(makename(lclname,TargetDir,file,U1Suffix),4) == 0)
if (getfa(lclname) == -1)
return 1;
#endif /* AMIGA */
#if ATARI_ST || HIGHC_386
{
FILE *f;
char lclname[MaxFileName];
if ((f = fopen(makename(lclname,TargetDir,file,U1Suffix), "r")) == NULL)
return 0;
else {
fclose(f);
return 1;
}
}
#endif /* ATARI_ST || HIGHC_386 */
#if MACINTOSH
#if MPW || LSC
{
FILE *f;
if ((f = fopen(file,"r")) != NULL) {
fclose(f);
return 1;
}
}
#endif /* MPW || LSC */
#endif /* MACINTOSH */
#if MSDOS
#if MICROSOFT || TURBO
struct stat statb;
if (access(file,4) == 0) {
stat(file,&statb);
if (statb.st_mode & S_IFREG)
return 1;
}
#else /* MICROSOFT || TURBO */
char lclname[MaxFileName];
if (access( makename(lclname,TargetDir,file,U1Suffix), 4 ) == 0 )
return 1;
#endif /* MICROSOFT || TURBO */
#endif /* MSDOS */
#if MVS || VM
FILE *f; /* can't use access because it will */
/* accept LRECL, etc. */
if ((f = fopen(file,"r")) != NULL {
fclose(f);
return 1;
}
#endif /* MVS || VM */
#if OS2
#if MICROSOFT
struct stat statb;
if (access(file,4) == 0) {
stat(file,&statb);
if (statb.st_mode & S_IFREG)
return 1;
}
#endif /* MICROSOFT || TURBO */
#endif /* OS2 */
#if UNIX
struct stat statb;
if (access(file,4) == 0) {
stat(file,&statb);
if (statb.st_mode & S_IFREG)
return 1;
}
#endif /* UNIX */
#if VMS
char lclname[MaxFileName];
if (access(makename(lclname,TargetDir,file,U1Suffix),4) == 0)
return 1;
#endif /* VMS */
/*
* End of operating-system specific code.
*/
return 0;
}
/*
* trypath - form a file name in file by concatenating name onto the
* next path element.
*/
static int trypath(name,file)
char *name, *file;
{
char c;
while (*pptr == ' ')
pptr++;
if (!*pptr)
return 0;
do {
c = (*file++ = *pptr++);
}
while (c != ' ' && c);
pptr--;
file--;
/*
* The following code is operating-system dependent [@lmem.04]. Append path
* character.
*/
#if PORT
/* nothing is needed */
Deliberate Syntax Error
#endif /* PORT */
#if AMIGA
file--;
switch (*file) {
case ':':
case '/':
file++;
break; /* add nothing, delimiter already there */
default:
*file++ = '/';
}
#endif /* AMIGA */
#if ATARI_ST || MACINTOSH || MVS || VM || VMS
/* nothing is needed */
#endif /* ATARI_ST || MACINTOSH */
#if HIGHC_386
*file++ = '\\';
#endif /* HIGHC_386 */
#if UNIX || MSDOS || OS2
*file++ = '/'; /* should check for delimiter */
#endif /* UNIX || MSDOS || OS2 */
/*
* End of operating-system specific code.
*/
while (*file++ = *name++);
*file = 0;
return 1;
}
/*
* alclfile - allocate an lfile structure for the named file, fill
* in the name and return a pointer to it.
*/
static struct lfile *alclfile(name)
char *name;
{
struct lfile *p;
p = (struct lfile *) alloc(sizeof(struct lfile));
p->lf_link = NULL;
p->lf_name = salloc(name);
return p;
}
#ifdef MultipleRuns
/*
* freelfile - free memory of an lfile structure.
*/
static novalue freelfile(p)
struct lfile *p;
{
free(p->lf_name);
free((char *) p);
}
#endif /* MultipleRuns */
/*
* lmfree - free memory used by the linker
*/
novalue lmfree()
{
struct lfile *lf, *nlf;
free((char *) lghash); lghash = NULL;
free((char *) lihash); lihash = NULL;
free((char *) lfhash); lfhash = NULL;
free((char *) lltable); lltable = NULL;
free((char *) lctable); lctable = NULL;
free((char *) lftable); lftable = NULL;
free((char *) lgtable); lgtable = NULL;
free((char *) litable); litable = NULL;
free((char *) lntable); lntable = NULL;
free((char *) lrtable); lrtable = NULL;
free((char *) lsspace); lsspace = NULL;
free((char *) fnmtbl); fnmtbl = NULL;
free((char *) labels); labels = NULL;
free((char *) codep); codep = NULL;
#ifdef MultipleRuns
for (lf = llfiles; lf != NULL; lf = nlf) {
nlf = lf->lf_link;
freelfile(lf);
}
llfiles = NULL;
#if MACINTOSH
#if MPW
/* #pragma unused(nlf,lf) */
#endif /* MPW */
#endif /* MACINTOSH */
#endif /* MultipleRuns */
}